﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.
using System;
using System.Linq;
using System.Threading.Tasks;

namespace MdeleteAPI
{
    class MdeleteAPI
    {
        //default parametr
        static bool bUseMulticore = false;
        static int iCountDeletedFiles = 0;
        static int iCountDeletedDirectory = 0;
        static string sDestinationDirectory = string.Empty;
        static bool bDeleteFile = false;

        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                string arg = args[0];

                //display help
                if (String.Compare(arg, "/?", false) == 0)
                {
                    Console.WriteLine("MdeleteAPI is program to delete long path in windows shell");
                    Console.WriteLine("Write at Ms-Pl license, read here http://www.opensource.org/licenses/ms-pl.html");
                    Console.WriteLine("MdeleteAPI version 1.0.0.1");
                    Console.WriteLine("Homepage project http://mdeleteapi.codeplex.com");
                    Console.WriteLine("");
                    Console.WriteLine("MDELETEAPI destination [/M] [/F]");
                    Console.WriteLine("");
                    Console.WriteLine("destination   Specifies destination directory and subdirectores or file");
                    Console.WriteLine("              to delete");
                    Console.WriteLine(@"              example: c:\destination or \\SERVER\destination");
                    Console.WriteLine(@"                       or \\127.0.0.1\destination");
                    Console.WriteLine("");
                    Console.WriteLine("/M            Use all core procesor in you computer");
                    Console.WriteLine("");
                    Console.WriteLine("/F            Delete specify file");
                    Console.WriteLine("              default destination is a folder");

                    return;
                }
                else
                {
                    string destinationDirectory = arg;
                    sDestinationDirectory = destinationDirectory;
                    StartDeleteFolder(destinationDirectory);
                }
            }
            else if (args.Length == 2)
            {
                Array.ForEach(args, arg =>
                {
                    if (String.Compare(arg.ToUpper(), "/M", false) == 0)
                        bUseMulticore = true;
                    else
                        if (String.Compare(arg.ToUpper(), "/F", false) == 0)
                            bDeleteFile = true;
                        else
                            sDestinationDirectory = arg;
                });
                if (bDeleteFile)
                    StartDeleteFile(sDestinationDirectory);
                else
                    StartDeleteFolder(sDestinationDirectory);             
            }
            else
            {
                Console.WriteLine("Invalid parametrs -> break program!");
                return;
            }
        }

        private static void StartDeleteFile(string destinationFile)
        {
            try
            {
                if (!APIFunction.ExistsFile(sDestinationDirectory))
                {
                    Console.WriteLine("Destination path doesn't exist or is unavailable -> break program!");
                    return;
                }

                var startTime = DateTime.Now;
                Console.WriteLine("Start Program: " + startTime);

                APIFunction.Delete_File(destinationFile);

                var stopTime = DateTime.Now;
                Console.WriteLine("Stop Program: " + stopTime);
                Console.WriteLine("Count deleted files      : " + iCountDeletedFiles);
                Console.WriteLine("All time delete this    : " + (stopTime - startTime));

                //bellow line only test develop
                //Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine("MdeleteAPI error: " + ex.Message);
            }
        }

        private static void StartDeleteFolder(string destinationDirectory)
        {
            try
            {
                if (!APIFunction.ExistsDirectory(destinationDirectory))
                {
                    Console.WriteLine("Destination path doesn't exist or is unavailable -> break program!");
                    return;
                }

                var startTime = DateTime.Now;
                Console.WriteLine("Start Program: " + startTime);

                DeleteLongFolder(destinationDirectory);
                if (APIFunction.ExistsDirectory(destinationDirectory))
                {
                    APIFunction.RemoveDirectory(destinationDirectory);
                }

                var stopTime = DateTime.Now;
                Console.WriteLine("Stop Program: " + stopTime);
                Console.WriteLine("Count deleted files      : " + iCountDeletedFiles);
                Console.WriteLine("Count deleted directory  : " + iCountDeletedDirectory);
                Console.WriteLine("All time delete this    : " + (stopTime - startTime));

                //bellow line only test develop
                //Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine("MdeleteAPI error: " + ex.Message);
            }
        }

        private static void DeleteLongFolder(string destinationDirectory)
        {
            if (bUseMulticore)
            {
                var t = Task.Factory.StartNew(() => Parallel.ForEach(APIFunction.EnumerateFiles(destinationDirectory), (file, loopStatus) =>
                {
                    APIFunction.Delete_File(file);
                    iCountDeletedFiles++;
                    Console.WriteLine("Delete file: " + APIFunction.ConvertToLongPath(file));
                }));
                t.Wait();
            }
            else
            {
                foreach (string file in APIFunction.EnumerateFiles(destinationDirectory))
                {
                    APIFunction.Delete_File(file);
                    iCountDeletedFiles++;
                    Console.WriteLine("Delete file: " + APIFunction.ConvertToLongPath(file));
                }
            }            

            string[] tabDir = APIFunction.EnumerateDirectories(destinationDirectory).ToArray();

            if (bUseMulticore)
            {
                var t1 = Task.Factory.StartNew(() => Parallel.ForEach(tabDir, (dir, loopStatus) =>
                {
                    if (APIFunction.ExistsDirectory(dir))
                        DeleteLongFolder(dir);
                }));
                t1.Wait();
            }
            else
            {
                Array.ForEach(tabDir, dir =>
                {
                    if (APIFunction.ExistsDirectory(dir))
                        DeleteLongFolder(dir);
                });
            }
            
            if (tabDir.Length == 0)
            {
                string rootFolder = destinationDirectory;
                rootFolder = rootFolder.Substring(0, rootFolder.LastIndexOf("\\"));
                APIFunction.Delete_Directory(destinationDirectory);
                iCountDeletedDirectory++;
                Console.WriteLine("Delete folder: " + APIFunction.ConvertToLongPath(destinationDirectory));
                if (String.Compare(destinationDirectory, sDestinationDirectory, false) == 0)
                {
                    return;
                }
                if (String.Compare(rootFolder, sDestinationDirectory, false) != 0)
                    DeleteLongFolder(rootFolder);
                else
                    return;
            }
        }
    }
}
